'''
Created on 22/10/2009

@author: eh01
'''
from Queue import Queue, Empty
from datastore.resource import Resource
from runtime import rt
from runtime.spaces import Spaces, SpacesContext
from services.timetask import TimeTask
import datetime
import time
import unittest

import logging
LOGGING = logging.WARNING
test_logger = logging.getLogger('test')
test_logger.setLevel(LOGGING)
streamHandler = logging.StreamHandler()
formatter = logging.Formatter("[%(asctime)s %(name)s %(levelname)s %(threadName)s] %(message)s")
streamHandler.setFormatter(formatter)
test_logger.addHandler(streamHandler)

class TimeTaskTest(unittest.TestCase):


    def setUp(self):
        queue = Queue()
        self.spaces = Spaces()
        spaces_context = SpacesContext(self.spaces, queue)
        runtime = rt.Runtime()
        runtime.initialise_spaces_with_local_config_files(spaces_context)       


    def tearDown(self):
        pass


    def test_cron(self):
        '''[TimeTask] test cron job''' 
        # dummy task def resource
        task_def_resource = Resource()
        uri_tasks = self.spaces.uri('tasks:')            
        uri_time = self.spaces.uri('time:')            
        time_task = TimeTask(self.spaces, uri_tasks.base.services.timetask, task_def_resource)
        client_queue = Queue()
        client_spaces_context = SpacesContext(self.spaces, client_queue)
        time_task.start()
        cron_resource = Resource()
        cron_resource.interval = 2
        # sleep here before we do a put to the time task as it has not completely initialised all its watches yet
        time.sleep(3)
        cron_uri = client_spaces_context.put(uri_time.cron.collection(True), cron_resource)
        client_spaces_context.watch(['put'], cron_uri.pop, 'dummy_callback')
        calls = 0
        while True:
            test_logger.log(logging.INFO, 'Waiting for callback')
            # wait for callback
            (process_callback, method, called_uri, return_value, result, spaces_context, kwargs) = client_queue.get(True)
            # check its the timer calling back by matching the uri and method
            self.assertEqual(called_uri, cron_uri.pop)
            self.assertEqual(method, 'put')
            # count the number of times we receive the callback
            calls += 1
            test_logger.log(logging.INFO, 'Call #' + str(calls))
            # once we reach the limit for cbs, then delete the time job
            if calls == 2:     
                client_spaces_context.delete(cron_uri)
                # wait a bit for the time job to shut down
                time.sleep(5)                
                # after waiting a bit after the time job shut down check that no cb's have been added to the queue
                self.assertRaises(Empty, client_queue.get, (False))
                time_task.task_stop()
                time.sleep(5)
                break
        

    def test_timer(self):
        '''[TimeTask] test timer job'''
        # dummy task def resource
        task_def_resource = Resource()
        uri_tasks = self.spaces.uri('tasks:')            
        uri_time = self.spaces.uri('time:')            
        time_task = TimeTask(self.spaces, uri_tasks.base.services.timetask, task_def_resource)
        client_queue = Queue()
        client_spaces_context = SpacesContext(self.spaces, client_queue)
        time_task.start()
        cron_resource = Resource()
        cron_resource.interval = 2
        # sleep here before we do a put to the time task as it has not completely initialised all its watches yet
        time.sleep(3)
        timer_uri = client_spaces_context.put(uri_time.timer.collection(True), cron_resource)
        client_spaces_context.watch(['put'], timer_uri.pop, 'dummy_callback')
        (process_callback, method, called_uri, return_value, result, spaces_context, kwargs) = client_queue.get(True)
        client_spaces_context.delete(timer_uri)
        # wait a bit for the time job to shut down
        time.sleep(3)
        # after waiting a bit after the time job shut down check that no cb's have been added to the queue
        self.assertRaises(Empty, client_queue.get, (False))
        time_task.task_stop()
        self.assertEqual(called_uri, timer_uri.pop)
        self.assertEqual(method, 'put')
        time.sleep(3)
    
    def test_cb_timestamp(self):
        '''[TimeTask] test Timestamp'''
        # dummy task def resource
        task_def_resource = Resource()
        uri_tasks = self.spaces.uri('tasks:')            
        uri_time = self.spaces.uri('time:')            
        time_task = TimeTask(self.spaces, uri_tasks.base.services.timetask, task_def_resource)
        client_queue = Queue()
        client_spaces_context = SpacesContext(self.spaces, client_queue)
        time_task.start()
        # sleep here before we do a get to the time task as it has not completely initialised all its watches yet
        time.sleep(3)
        timestamp_resource = client_spaces_context.get(uri_time.timestamp)
        time_task.task_stop()        
        self.assertTrue(type(timestamp_resource.timestamp), type(datetime.datetime.now()))
        
                    
if __name__ == "__main__":
    #import sys;sys.argv = ['', 'Test.testName']
    unittest.main()